#encoding=utf8
'''
Created on Sep 12, 2014

@author: jingyang <jingyang@smalltreemedia.com>
'''
from django.db import models
from django.utils import timezone
from django import forms

from utils import field
from core.fields import CustomCharField, CustomTextField
from core.widgets import CustomTextarea
import datetime
from sub_info.models import ReviewStatus, SubInfo
from qa_info.models import DevQAInfo, ReleaseQAInfo
from django.contrib.auth.models import User, Group


class Company(models.Model):
    name = models.CharField(u'Company Name', max_length=100)
    display_name = models.CharField(u'Company Display Name', max_length=10)
    location = models.CharField(u'Location', max_length=100)
    code = models.CharField(u'Company Code', max_length=10, unique=True, help_text=u'e.g. CD')

    def __unicode__(self):
        return self.display_name

    class Meta:
        verbose_name = u'Company'
        verbose_name_plural = u'Companys'


class CompanyGroup(models.Model):
    group = models.OneToOneField(Group)
    company = models.ForeignKey(Company, verbose_name=u'CompanyGroup', null=True, blank=True, on_delete=models.SET_NULL)

    def __unicode__(self):
        return self.company.name + '-' + self.group.name

    class Meta:
        verbose_name = u'Permission Group'
        verbose_name_plural = u'Permission Groups'


class StudioCloud(models.Model):
    cloud_id = models.CharField(u'Cloud ID', max_length=20, null=True, blank=True)
    cloud_purpose = models.CharField(u'Cloud Purpose', max_length=2000, null=True, blank=True)
    parent_brand = models.CharField(u'Parent Brand', max_length=50, null=True, blank=True)

    def __unicode__(self):
        return self.cloud_id

    def get_parent_brand(self):
        try:
            return Studio.objects.get(id=self.parent_brand)
        except Exception, e:
            return ''

    class Meta:
        verbose_name = u'Studio Clouds'
        verbose_name_plural = u'Studio Clouds'
        ordering = ('cloud_id',)


class Studio(models.Model):
    custom_id = models.CharField(u'Studio ID', max_length=100, null=True,
        blank=True, default='')
    pub_name = models.CharField(u'Studio Name', max_length=50, null=True, blank=True)
    prd_name = models.CharField(u'2nd Studio Name', max_length=50, null=True, blank=True)
    ios_code_format = models.CharField(u'App Code Format (iOS)', max_length=100,
        null=True, blank=True, default='')
    gp_code_format = models.CharField(u'App Code Format (GP)', max_length=100,
        null=True, blank=True, default='')
    amz_code_format = models.CharField(u'App Code Format (Amz)', max_length=100,
        null=True, blank=True, default='')
    bundle_id = models.TextField(u'Bundle ID Prefix', null=True, blank=True, default='')
    code = models.CharField(u'URL Scheme Prefix', max_length=10, help_text=u'<strong><i>Studio abbreviation</i></strong>',
        null=True, blank=True, default='')
    service_site = models.URLField(u'Central Services base domain', null=True, blank=True, default='')
    website = models.URLField(u'Website', null=True, blank=True, default='')
    app_store_id = models.CharField(u'App Store ID', max_length=20, null=True, blank=True, default='')
    cloud = models.ForeignKey(StudioCloud, verbose_name=u'Cloud', null=True,
        blank=True, on_delete=models.SET_NULL)

    available_store = models.CharField(u'App Store Availability', max_length=200,
        null=True, blank=True, default='')

    copy_right = models.CharField('Copy Right Name', max_length=50, null=True, blank=True)
    main_domain = models.CharField('1st Domain', max_length=100, null=True, blank=True)
    alt_domain = models.CharField('2nd Domain', max_length=100, null=True, blank=True)
    studio_code = models.CharField('Studio Code', max_length=5, null=True, blank=True)
    production_location_assignment = models.CharField('Production Location Assignment', max_length=100, null=True, blank=True)

    def __unicode__(self):
        return u'%s - %s' % (self.custom_id, self.pub_name if not self.prd_name else '%s (%s)' % (self.pub_name, self.prd_name))

    class Meta:
        verbose_name = u'Studio'
        verbose_name_plural = u'Studios'
        ordering = ('custom_id', 'pub_name')


PLATFORM = (
    ('I', u'iOS'),
    ('A', u'Android'),
)


STATUS = (
    ('P', u'Pending'),
    ('V', u'Valid'),
    ('I', u'Invalid'),
    ('Z', u'Cancelled'),
)


TYPE = (
    ('N', u'New App'),
    ('U', u'Binary Update'),
    ('C', u'Back-end Content Update'),
    ('R', u'Binary Resub'),
)


ADS_TYPE = (
    ('O', u'3rd Party Ads only'),
    ('P', u'3rd Party Ads + Cross Promo Ads'),
    ('N', u'No Ads'),
)


KIDS_CATE = (
    ('Y', u'Yes'),
    ('N', u'No'),
    ('U', u'N/A'),
)


PUSH_TYPE = (
    ('I', u'iOS Push Notification'),
    ('G', u'Google GCM'),
    ('N', u'No'),
)


RELEASE_REQ = (
    ('A', u'Auto Release'),
    ('M', u'Manual Release'),
)


SUPPORTED_DEVICES = (
    ('ALL IOS', u'ALL iOS Device - Universal'),
    ('ONLY IPHONE', u'iPhone/iPod touch Only'),
    ('ONLY IPAD', u'iPad Only'),
    ('ALL ANDROID', u'ALL Android Devices'),
)


APP_STORE = (
    ('iTunes App Store', u'iTunes App Store'),
    ('Google Play', u'Google Play'),
    ('Amazon App Store', u'Amazon App Store'),
)


YES_OR_NO = (
    ('', '---------'),
    ('Y', 'Yes'),
    ('N', 'No'),
)


class App(models.Model):
    prd_id = models.CharField('Product ID', max_length=10, unique=True)
    prj_code = models.CharField(u'App Code', max_length=50, unique=True,
        help_text=u"""<strong><i>Replace XXX to number</i></strong>""")
    old_prj_code = models.CharField(u'App Code (Alternative)', max_length=50, default='', null=True, blank=True)
    app_name = CustomCharField(u'App Name (Production)', max_length=1000,
        widget=forms.TextInput(attrs={'style': '''width: 500px;'''}))
    pub_name = CustomCharField(u'App Name (Publish)', max_length=1000,
        widget=forms.TextInput(attrs={'style': '''width: 500px;'''}), null=True, blank=True,
        default='')
#    display_name = models.CharField(u'Display Name', max_length=128, null=True, blank=True)
    bundle_id_suffix = models.CharField(u'Bundle ID Suffix', max_length=100)
    bundle_id_prefix = models.CharField(u'Bundle ID Prefix', max_length=100)
    app_id = CustomCharField(u'Apple ID', max_length=20, null=True, blank=True, default='')
    store_link = models.CharField(u'Store Link', max_length=200, null=True, blank=True, default='')
    platform = models.CharField(u'Platform', max_length=1, choices=PLATFORM)
    app_store = models.CharField(u'App Store', max_length=50)
    studio = models.ForeignKey(Studio, verbose_name=u'Publish Studio',
        help_text=u'<strong><i>Select the studio that your app will be launched to</i></strong>')

#    type = models.CharField(u'App Production Type', max_length=1, choices=TYPE, null=True, blank=True)
#    version = models.CharField(u'Version Code', max_length=10, null=True, blank=True,
#        help_text=u"""<strong><i>Start with "V", e.g. V1.0</i></strong>""")
#    eta_to_qa = models.DateField(u'Estimated Date to QA', null=True, blank=True,
#        help_text=u'<strong><i>When will your app be submitted to QA?</i></strong>')
#    eta_qa_time = models.CharField(u'Estimated QA Time', max_length=50, null=True, blank=True,
#        help_text=u'<strong><i>How long will the full test of your app take?</i></strong>')
#    fe = models.CharField(u'Front-end Programmer', max_length=20, null=True, blank=True)
#    be = models.CharField(u'Back-end Programmer', max_length=20, null=True, blank=True)
#    ads_type = models.CharField(u'Has Ads in this version?', max_length=1, choices=ADS_TYPE, null=True, blank=True,
#        help_text=u'<strong><i>Provide this info according to your app setting so that QA can test the Ads out</i></strong>')
#    kids_cate = models.CharField(u'Included in KIDS category?', max_length=1, choices=KIDS_CATE, null=True, blank=True,
#        help_text=u'<strong><i>Choose "YES" or "NO" for iOS apps<br/>Choose "N/A" for all Android apps</i></strong>')
#    push = models.CharField(u'Push Notification', max_length=1, choices=PUSH_TYPE, null=True, blank=True,
#        help_text=u'<strong><i>Is Push Notification Enabled for this app? On Android it was called GCM</i></strong>')
#    supported_devices = models.CharField(u'Supported Devices', max_length=200, null=True, blank=True)
#    release_req = models.CharField(u'Release Date Request', max_length=1, choices=RELEASE_REQ,
#        help_text=u"""<strong><i>Choose "Auto Release" if you don't have special
#                      requirement on release date</i></strong>""", null=True, blank=True)
#    intro = models.TextField(u"App Intro / What's NEW?", null=True, blank=True,
#        help_text=u'''<strong><i>For new apps, please briefly introduce your app
#                      <br />For updates, please list out details of all changes
#                      made with this update</i></strong>''')

    editor = models.EmailField(u'Editor Email', null=True, blank=True)
    create_time = models.DateTimeField(u'Created Time', auto_now_add=True)
    status = CustomCharField(u'Validation', max_length=1, choices=STATUS,
        default='P', widget=forms.Select(attrs={'style': '''width: 100px;'''}))
    notes = CustomTextField(u'Notes', null=True, blank=True, default='',
        widget=CustomTextarea)

    flurry_key = models.CharField('Flurry Key', max_length=50, null=True,
        blank=True, default='')

    valid_time = models.DateTimeField('Valid Time', null=True, blank=True)
    valid_person = models.CharField('Valid Person', max_length=50, null=True,
        blank=True, default='')

    pub_key = CustomTextField('Public Key', null=True, blank=True, default='',
        widget=CustomTextarea({'style': '''overflow: hidden; word-wrap: break-word;
            resize: horizontal; width: 800px; height: 200px;'''}))

    ga_key = models.CharField('Google Analytics Key', max_length=200, null=True,
                              blank=True)
    quantcast_key = models.CharField('QuantCast Key', max_length=200, null=True, blank=True)
#    iap_required = models.CharField('Required IAP Request?', max_length=1,
#        choices=YES_OR_NO)
#    ads_required = models.CharField('Required Ads Request?', max_length=1,
#        choices=YES_OR_NO)

    # add company
    company = models.ForeignKey(Company, verbose_name='Company', null=True, blank=True, on_delete=models.SET_NULL, )

    def get_full_bundle_id(self):
        return self.bundle_id_prefix + self.bundle_id_suffix

    def get_local_create_time(self):
        return timezone.localtime(self.create_time).strftime('%Y-%m-%d %H:%M:%S')

    def get_url_scheme(self):
        if self.studio.code:
            return '%s-%s' % (self.studio.code.lower(), self.bundle_id_suffix)
        return ""

    def get_app_store_icon(self):
        pic = ''
        if self.app_store == 'iTunes App Store':
            pic = 'app_store.png'
        elif self.app_store == 'Google Play':
            pic = 'google_play.png'
        elif self.app_store == 'Amazon App Store':
            pic = 'amz_store.png'
        return "<center><img src='/static/base/img/%s' width=20 height=20 /></center>" % pic\
            if pic else self.app_store

    def get_initial_release_date(self):
        v1 = self.appversion_set.filter(code='1.0', status='L')[:1]
        if not v1:
            return ''
        return v1[0].date_released or ''

    def get_division(self):
        v1 = self.appversion_set.filter(code='1.0')
        return v1[0].get_division() if v1 else ''

    def get_team(self):
        v1 = self.appversion_set.filter(code='1.0')
        return v1[0].get_team() if v1 else ''

    def __unicode__(self):
        return '%s (%s)' % (self.prj_code, self.app_name)

    class Meta:
        verbose_name = u'App'
        verbose_name_plural = u'Apps'
        ordering = ('status', '-prd_id')


#ORIENTATION = (
#    ('', u'---------'),
#    ('P', u'Portrait'),
#    ('L', u'Landscape'),
#    ('B', u'Both')
#)


SPECIAL_SETTINGS = (
    ('STKC', 'Submit to KIDS Category (COPPA Complaint)'),
    ('HPN', 'Has Push Notification'),
    ('DNSI', 'Does not Support iPad'),
    ('SIDO', 'Support iPad Devices Only'),
    ('SI4AB', 'Support iOS 4.X and below'),
)


class AppExtraInfo(models.Model):
    app = models.OneToOneField(App, verbose_name=u'App', null=True, blank=True)
    flurry_key = models.CharField(u'Flurry Key', max_length=100, default='',
        null=True, blank=True)
    media_local = models.CharField(u'Product Submission Doc (Local)', max_length=1000,
        default='', null=True, blank=True)
    media_remote = models.CharField(u'Product Submission Doc (Dropbox)', max_length=1000,
        default='', null=True, blank=True)
    display_name = models.CharField(u'Display Name on Device', max_length=200,
        null=True, blank=True, default='')
    special = models.CharField(u'Special Settings', max_length=200, null=True,
        blank=True)
#    cross_local = models.CharField(u'Cross Promo Creatives (Local)', max_length=1000,
#        default='', null=True, blank=True)
#    cross_remote = models.CharField(u'Cross Promo Creatives (Dropbox)', max_length=1000,
#        default='', null=True, blank=True)
#    orientation = models.CharField(u'Orientation', max_length=1,
#        choices=ORIENTATION, default='', null=True, blank=True)

    def __unicode__(self):
        return 'Extra info of %s' % self.app

    class Meta:
        verbose_name = u'App Extra Info'
        verbose_name_plural = u'App Extra Info'


class UserGroup(models.Model):
    name = models.CharField(u'Division Name', max_length=50, null=True, blank=True)
#    user = models.ManyToManyField(User, verbose_name=u'PJMs', related_name='users',
#        null=True, blank=True, limit_choices_to={'is_active': True, 'is_staff': True})
    owner = models.ForeignKey(User, verbose_name=u'Division Head', related_name='pm',
        null=True, blank=True, on_delete=models.SET_NULL)
    studios = models.ManyToManyField(Studio, verbose_name=u'Available Studios', null=True, blank=True)
    clouds = models.ManyToManyField(StudioCloud, verbose_name='Available Studio Clouds',
        null=True, blank=True)

    def __unicode__(self):
        return self.name

    def get_included_studios(self, id=False):
        studios = []
        for c in self.studios.all():
            studios.append(c)
        studios = list(set(studios))
        ids = [s.pk for s in studios]
        return ids if id else Studio.objects.filter(id__in=ids)

    class Meta:
        verbose_name = u'Division'
        verbose_name_plural = u'Division'


DIVISION = (
    ('FPG', 'FPG'),
    ('KTG', 'KTG'),
    ('NPD', 'NPD')
)


class ProductionTeam(models.Model):
    name = models.CharField('Team Name', max_length=50, null=True, blank=True)
    user = models.ManyToManyField(User, verbose_name=u'PJMs', related_name='teams',
                                  null=True, blank=True, limit_choices_to={'is_active': True, 'is_staff': True})
    group = models.ForeignKey(UserGroup, verbose_name='Division', null=True, blank=True,
                              on_delete=models.SET_NULL)
    company = models.ForeignKey(Company, verbose_name='Company', null=True, blank=True, on_delete=models.SET_NULL)
    division = models.CharField('Division', max_length=100, null=True, blank=True, choices=DIVISION)

    studios = models.ManyToManyField(Studio, verbose_name='Available Studios',
                                     null=True, blank=True)

    def __unicode__(self):
        return self.name

    def get_included_studios(self, id=False):
        studios = []
        for c in self.studios.all():
            studios.append(c)
        studios = list(set(studios))
        ids = [s.pk for s in studios]
        return ids if id else Studio.objects.filter(id__in=ids)

    class Meta:
        verbose_name = 'Production Team'
        verbose_name_plural = 'Production Teams'
        ordering = ('name',)


PRODUCTION_STATUS = (
    ('I', 'In Production'),
    ('C', 'Cancelled'),
    ('S', 'Submitted'),
    ('L', 'Live'),
    ('O', 'On Hold'),
)


PRODUCTION_TYPE = (
    ('N', 'New'),
    ('U', 'Update'),
)


PURPOSE = (
    ('RAIOR', 'Refresh App Image / Repackage'),
    ('AMGAC', 'Add more Gameplay & Content'),
    ('UAOCP', 'Update Ads / Cross'),
    ('SMOSVAD', 'Support more OS versions & Devices'),
    ('BFAOP', 'Bug Fixes & Optimization'),
    ('OTHER', 'Other'),
)


class AppVersion(models.Model):
    log_id = models.CharField('Version Log ID (Production Task ID)', max_length=20)
    app = models.ForeignKey(App, verbose_name=u'App')
    code = models.CharField(u'Version Number', max_length=11, default='1.0')
    type = CustomCharField(u'Production Type', max_length=1,
        choices=PRODUCTION_TYPE, default='U',
        widget=forms.Select(attrs={'style': '''width: 100px;'''}))
    create_time = models.DateTimeField(u'Date Created', auto_now_add=True)
    purpose = models.CharField(u'Production Purpose', max_length=100, null=True,
        blank=True, default='')
    editor = models.CharField(u'Created By', max_length=200, null=True, blank=True,
        default='')
    owner = models.CharField(u'Project Coordinator', max_length=200)
    product_owner = models.CharField('Product Owner', max_length=200)
    status = models.CharField(u'Production Status', max_length=1,
        choices=PRODUCTION_STATUS, default='I')
    change_list = models.TextField("What's new in this version",
        null=True, blank=True, default='')

    iap_required = models.CharField('Has IAP?', max_length=1,
        choices=YES_OR_NO, default='', null=True, blank=True)
    ads_required = models.CharField('Has Ads?', max_length=1,
        choices=YES_OR_NO, default='', null=True, blank=True)
    cross_promo_required = models.CharField('Has Cross Promo?', max_length=1,
        choices=YES_OR_NO, default='', null=True, blank=True)

    date_submitted = models.DateField('Submitted Date', null=True, blank=True)
    ref_id = models.CharField('Production Brief Ref ID', max_length=50, null=True,
        blank=True, default='')
    
    link_of_product_brief=models.CharField('Link of Product Brief',max_length=200,
         null=True,blank=True,default='')
    
    programmer = models.CharField('Front-end Engineer', max_length=100,
        null=True, blank=True)

    date_released = models.DateField('Released Date', null=True, blank=True)

    code_dir = models.TextField('Code Directory', null=True, blank=True)

    prd_team = models.ForeignKey('ProductionTeam', verbose_name='Production Team',
        null=True, blank=True)

    sdk_required = models.ManyToManyField('sdk_info.SDKVersion',
                                          verbose_name='SDK in Use',
                                          null=True, blank=True,
                                          limit_choices_to={'status': 'A'})

    def __unicode__(self):
        return "V%s of %s" % (self.code, self.app)

    def get_sdk_required_display(self):
        return self.sdk_required.all()

    def get_coordinator(self, name=True):
        try:
            user = User.objects.get(id=self.owner)
            if name:
                return user.username
            return user
        except User.DoesNotExist:
            return ''

    def get_team(self, name=True):
        if not self.prd_team:
            return ''
        return self.prd_team if not name else self.prd_team.name
#        pjm = self.get_coordinator(False)
#        if pjm:
#            team = pjm.teams.all()[:1]
#            if team:
#                if name:
#                    return team[0].name
#                return team[0]
#        return ''

    def get_division(self):
        team = self.get_team(False)
        if team:
            return team.group.name if team.group else ''
        return ''

    def get_release_date(self):
        return self.date_released or ''

    def get_purpose(self):
        if self.purpose == 'New App':
            return self.purpose
        purpose = str(self.purpose).replace('[', '').replace(']', '').\
            replace("u'", '').replace("'", '').split(', ')
        return ','.join([dict(PURPOSE).get(d, '') for d in purpose])

    def get_dev_qa(self):
        return DevQAInfo.objects.filter(app=self.app, version=self.code)

    def get_release_qa(self):
        return ReleaseQAInfo.objects.filter(dev_qa__app=self.app, dev_qa__version=self.code)

    def get_sub_info(self):
        sub_info = SubInfo.objects.filter(app=self.app, version=self.code)[:1]
        return sub_info[0] if sub_info else None

    class Meta:
        verbose_name = u'App Version'
        verbose_name_plural = u'App Version'


KEY_STATUS = (
    ('S', 'Pending Creation'),
    ('R', 'Ready'),
    ('C', 'Cancelled'),
)


class BaseKeyReqManager(models.Manager):
    def get_latest_num(self):
        current_year = timezone.now().year
        current_month = timezone.now().month
        current_day = timezone.now().day
        latest = self.filter(create_time__year=current_year, create_time__month=current_month,
            create_time__day=current_day).order_by('-request_id')[:1]
        return int(latest[0].request_id[-2:]) + 1 if latest else 1


class BaseKeyReq(models.Model):
    request_id = models.CharField('Request ID', max_length=20)
    app = models.ForeignKey(App, verbose_name='App', null=True, blank=True,
        limit_choices_to={'status': 'V'})
    added_at = models.DateTimeField('Fulfilled at', null=True, blank=True)
    create_time = models.DateTimeField('Created Time', auto_now_add=True)
    editor = models.CharField('Fulfilled by', max_length=50, null=True, blank=True,
        default='')
    status = models.CharField('Status', max_length=1, choices=KEY_STATUS,
        default='S')

    objects = BaseKeyReqManager()

    def get_status_mark(self):
        if self.status == 'S':
            cls = 'label-warning'
        elif self.status == 'R':
            cls = 'label-success'
        else:
            cls = ''
        return "<span class='label %s' style='width: 85px;'><center>%s</center></span>" %\
            (cls, self.get_status_display())

    class Meta:
        abstract = True


class AppleID(BaseKeyReq):
    itunes_id = models.CharField('iTunes ID', max_length=20, null=True,
        blank=True, default='')

    def __unicode__(self):
        return 'iTunes ID of %s' % self.app.prj_code

    class Meta:
        verbose_name = 'Apple ID'
        verbose_name_plural = 'Apple ID'
        ordering = ('-status',)


class FlurryKey(BaseKeyReq):
    key = models.CharField('Flurry Key', max_length=50, null=True, blank=True,
        default='')

    def __unicode__(self):
        return 'Flurry Key of %s' % self.app.prj_code

    class Meta:
        verbose_name = 'Flurry Key'
        verbose_name_plural = 'Flurry Key'
        ordering = ('-status',)


class GAKey(BaseKeyReq):
    key = models.CharField('Google Analytics Key', max_length=200, null=True,
                           blank=True)

    def __unicode__(self):
        return 'Google Analytics Key of %s' % self.app.prj_code

    class Meta:
        verbose_name = 'GA Key'
        verbose_name_plural = verbose_name
        ordering = ('-status',)


class QuantCastKey(BaseKeyReq):
    key = models.CharField('QuantCast Key', max_length=200, null=True, blank=True)

    def __unicode__(self):
        return 'QuantCast Key of %s' % self.app.prj_code

    class Meta:
        verbose_name = 'QuantCast Key'
        verbose_name_plural = verbose_name
        ordering = ('-status',)
